﻿using Application.Common.Interfaces;
using Domain.Entities.Organizations;
using FluentValidation;
using Microsoft.EntityFrameworkCore;
using System;

namespace Application.Features.Organizations.Commands.Update;

/// <summary>
/// 校验添加组织机构信息
/// </summary>
public class UpdateOrganizationCommandValidator : AbstractValidator<UpdateOrganizationCommand>
{
    private readonly IApplicationDbContext _context;
    public UpdateOrganizationCommandValidator(IApplicationDbContext context)
    {
        _context = context;

        RuleFor(x => x.OrganizationName)
            .NotNull().WithMessage("组织机构名称不能为空！")
            .MustAsync(OrganizationNameExistsAsync).WithMessage("组织机构名称重复！");

        RuleFor(x => x.ParentId).MustAsync(ValidParentIdAsync).WithMessage("非法移动！");
        RuleFor(x => x.OrganizationId).MustAsync(ValidIsNotSubordinateAsync).WithMessage("非法移动！");
        RuleFor(x => x.OrganizationPrincipalId).MustAsync(OrganizationPrincipalExistsAsync).WithMessage("非法数据！");
    }

    /// <summary>
    /// 组织机构移动是否合法
    /// </summary>
    /// <param name="command"></param>
    /// <param name="parentId"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    private async Task<bool> ValidParentIdAsync(UpdateOrganizationCommand command, long? parentId, CancellationToken cancellationToken)
    {
        if (parentId == null)
            return true;

        if (command.OrganizationId == parentId) 
            return false;

        return await _context.Organizations.AnyAsync(x => x.Id == parentId, cancellationToken);
    }

    /// <summary>
    /// 组织机构负责人是否存在
    /// </summary>
    /// <param name="organizationPrincipalId"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    private async Task<bool> OrganizationPrincipalExistsAsync(long? organizationPrincipalId, CancellationToken cancellationToken)
    {
        if (organizationPrincipalId == null) return true;

        return await _context.Users.AnyAsync(x => x.Id == organizationPrincipalId, cancellationToken);
    }

    /// <summary>
    /// 校验组织机构名称重复
    /// </summary>
    /// <param name="command"></param>
    /// <param name="organizationName"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    private async Task<bool> OrganizationNameExistsAsync(UpdateOrganizationCommand command,string? organizationName, CancellationToken cancellationToken)
    {
        var organization = await _context.Organizations.SingleOrDefaultAsync(x => x.OrganizationName == organizationName);
        if (organization == null) return true;

        return organization.Id == command.OrganizationId;
    }

    /// <summary>
    /// 校验不是下级
    /// </summary>
    /// <param name="command"></param>
    /// <param name="Id"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    private async Task<bool> ValidIsNotSubordinateAsync(UpdateOrganizationCommand command, long Id, CancellationToken cancellationToken)
    {
        if (!command.ParentId.HasValue) return true;

        var organizations = await _context.Organizations.ToListAsync();
        if (!organizations.Any()) return true;

        return !GetSubOrganizations(organizations, Id).Any(x => x.Id == command.ParentId);


        static IEnumerable<Organization> GetSubOrganizations(List<Organization> organizations, long Id)
        {
            var subOrganizations = organizations.Where(d => d.ParentId == Id).ToList();
            foreach (var organization in subOrganizations.ToList()) // 使用 ToList() 创建一个副本以避免修改正在迭代的集合
            {
                subOrganizations.AddRange(GetSubOrganizations(organizations, organization.Id));
            }
            return subOrganizations;
        }
    }
}
